﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Engine.cs" company="Skymate">
//   Copyright © 2015 Skymate. All rights reserved.
// </copyright>
// <summary>
//   引擎核心.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Skymate.Engines
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    using Castle.MicroKernel.Registration;
    using Castle.Windsor;

    using Skymate.Core;
    using Skymate.Data;
    using Skymate.Engines.DependencyManagement;
    using Skymate.Extensions;

    /// <summary>
    ///     引擎核心.
    ///     提供核心的实现部分,具体的应用有不同的实现方式
    /// </summary>
    public class Engine : IEngine
    {
        #region 属性

        /// <summary>
        ///     容器.
        /// </summary>
        public IWindsorContainer Container
        {
            get
            {
                return this.ContainerManager.IocContainer;
            }
        }

        /// <summary>
        ///     容器管理器.
        /// </summary>
        public IIocManager ContainerManager { get; private set; }

        #endregion

        #region 方法

        /// <summary>
        ///     初始化组件和插件.
        /// </summary>
        public void Initialize()
        {
            this.ContainerManager =  this.RegisterDependencies();

            this.RunStartupTasks();
            /*if (DataSettings.DatabaseIsInstalled())
            {
                
            }*/
        }

        /// <summary>
        /// 解析.
        /// </summary>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <typeparam name="T">
        /// </typeparam>
        /// <returns>
        /// The <see cref="T"/>.
        /// </returns>
        public T Resolve<T>(string name = null) where T : class
        {
            if (name.HasValue())
            {
                return this.ContainerManager.Resolve<T>(name);// .ResolveNamed<T>(name);
            }

            return this.ContainerManager.Resolve<T>();
        }

        /// <summary>
        /// The resolve.
        /// </summary>
        /// <param name="type">
        /// The type.
        /// </param>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <returns>
        /// The <see cref="object"/>.
        /// </returns>
        public object Resolve(Type type, string name = null)
        {
            if (name.HasValue())
            {
                return this.ContainerManager.Resolve(type,name);// .ResolveNamed(name, type);
            }

            return this.ContainerManager.Resolve(type);
        }

        /// <summary>
        ///     The resolve all.
        /// </summary>
        /// <typeparam name="T">
        /// </typeparam>
        /// <returns>
        ///     The <see cref="T[]" />.
        /// </returns>
        public T[] ResolveAll<T>()
        {
            return null;/*
            return this.ContainerManager.r .ResolveAll<T>();*/
        }

        #endregion

        #region Utilities

        /// <summary>
        ///     启动任务.
        /// </summary>
        protected virtual void RunStartupTasks()
        {
            var typeFinder = this.ContainerManager.Resolve<ITypeFinder>();
            var startUpTaskTypes = typeFinder.FindClassesOfType<IStartupTask>(ignoreInactivePlugins: true);
            var startUpTasks = new List<IStartupTask>();

            foreach (var startUpTaskType in startUpTaskTypes)
            {
                startUpTasks.Add((IStartupTask)Activator.CreateInstance(startUpTaskType));
            }

            // 按顺序执行异步任务
            var groupedTasks = startUpTasks.OrderBy(st => st.Order).ToLookup(x => x.Order);
            foreach (var tasks in groupedTasks)
            {
                Parallel.ForEach(tasks, task => { task.Execute(); });
            }
        }

        /// <summary>
        ///     创建类型发现.
        /// </summary>
        /// <returns>
        ///     <see cref="ITypeFinder" />.
        /// </returns>
        protected virtual ITypeFinder CreateTypeFinder()
        {
            return new WebAppTypeFinder();
        }

        /// <summary>
        ///     注册依赖项，具体子类实现.
        /// </summary>
        /// <returns>
        ///     <see cref="ContainerManager" />.
        /// </returns>
        protected IIocManager RegisterDependencies()
        {

            var iocManager = IocManager.Instance;

            var typeFinder = this.CreateTypeFinder();

            // 注册IEngine
            iocManager.IocContainer.Register(
                Component.For<IEngine>()
                .UsingFactoryMethod(() => this)
                .LifestyleSingleton());

            // 注册 TypeFinder
            iocManager.IocContainer.Register(
                Component
                .For<ITypeFinder>()
                .UsingFactoryMethod(() => typeFinder)
                .LifestyleSingleton());
            
            var registrarTypes = typeFinder.FindClassesOfType<IDependencyRegistrar>();
            var registrarInstances = new List<IDependencyRegistrar>();
            foreach (var type in registrarTypes)
            {
                registrarInstances.Add((IDependencyRegistrar)Activator.CreateInstance(type));
            }

            registrarInstances = registrarInstances.AsQueryable().OrderBy(t => t.Order).ToList();
            foreach (var registrar in registrarInstances)
            {
                registrar.Register(iocManager, typeFinder, false);
            }

            return iocManager;
            
        }

        #endregion
    }
}